﻿#include "thread_cpy.hpp"

void threaded_memory_copy(char* destination, char* source, 
                         size_t length, int data_size, size_t stride, int thread_count) {
    if (thread_count > static_cast<int>(length >> 8)) {
        thread_count = static_cast<int>(length >> 8);
    }
    if (thread_count < 1) thread_count = 1;
    
    size_t block_length = length / thread_count;
    size_t remainder = length % thread_count;
    size_t block_size = block_length * data_size;
    
    std::vector<std::thread> threads;
    threads.reserve(thread_count);
    
    for (int i = 0; i < thread_count - remainder; i++) {
        if (stride == data_size) {
            threads.emplace_back(std::memcpy, destination, source, block_size);
        } else {
            threads.emplace_back(custom_memcpy, destination, source, 
                               block_length, data_size, stride);
        }
        destination += block_size;
        source += block_length * stride;
    }
    
    block_length++;
    block_size += data_size;
    for (int i = thread_count - remainder; i < thread_count; i++) {
        if (stride == data_size) {
            threads.emplace_back(std::memcpy, destination, source, block_size);
        } else {
            threads.emplace_back(custom_memcpy, destination, source, 
                               block_length, data_size, stride);
        }
        destination += block_size;
        source += block_length * stride;
    }
    
    for (auto& thread : threads) {
        thread.join();
    }
}